#ifndef UCN2IC10ImplementationH
#define UCN2IC10ImplementationH

#include "../UControlContainerWindow.h"
#include "../Controls/UMemo.h"
#include "../Controls/UEdit.h"
#include "../Controls/UTextButton.h"

#include <SDL/SDL_net.h>

#include <boost/shared_ptr.hpp>

#include <map>

class TCN2IC10MainWindow;
class TCN2IC10ChatWindow;

enum NetState {
	NET_STATE_NONE,               // initial state
	NET_STATE_INITIALISED,        // network is initialised, socket is opened
	NET_STATE_USERNAME_REQUESTED, // credientials have been requested
	NET_STATE_USERNAME_CONFIRMED, // request has been confirmed
	NET_STATE_LOGIN_REQUESTED,    // login information has been sent
	NET_STATE_LOGIN_CONFIRFMED,   // login was successfull

	NET_STATE_ERROR,              // there has been an error
};

// holds information about a user
struct UserInfo
{
	bool online;  // whether user is online or not
	IPaddress addr; // only valid when online == true
	TCN2IC10ChatWindow* window;
	UserInfo() : online(false), window(NULL) { addr.host = 0; };
};

// item in the outgoing message queue
struct OutMessage
{
	std::string destuser;
	TCPsocket sock;
	uint16 port;
	bool connected;
	std::vector<uint8> data;
	uint32 outpos;
	OutMessage();
	~OutMessage();
};
typedef boost::shared_ptr<OutMessage> OutMessageRef;

// item in the incoming message queue
struct InMessage
{
	std::string srcuser;
	TCPsocket sock;
	uint16 port;
	bool connected;
	std::vector<uint8> data;
	uint32 size;
	uint32 inpos;
	uint8 type;
};
typedef boost::shared_ptr<InMessage> InMessageRef;

class CN2IC10Implementation
{
	private:
		TCN2IC10MainWindow* mainWindow;              ///< reference to the main window
		NetState netstate;                           ///< stores current state, see above enum
		uint32 ticks;                                ///< amount of ticks we've been in the current state
		IPaddress servaddr;                          ///< stores server adress, if known
		std::map<std::string, UserInfo> userinfo;    ///< maps usernames to user info
		std::vector<OutMessageRef> outqueue;         ///< outgoing message queue
		std::vector<InMessageRef> inqueue;           ///< incoming message queue
	public:
		/// Gui elements for main window
		TMemo onlineUsers;
		TMemo offlineUsers;
		TTextButton buttonChangeUserName;
		TTextButton buttonManualUserAdd;
		TEdit editUserName;
		TEdit editUserAdd;

		/// current username/password
		std::string username;
		std::string password;

		/// contructor
		CN2IC10Implementation(TCN2IC10MainWindow* main);

		// udp socket and packet
		UDPsocket udpSock; ///< direct send/receive socket
		UDPsocket bcSock;  ///< broadcast receive socket
		UDPpacket* udpPacket;

		// ticker function, get called 10 times a sec and does everything
		void Ticker();

		/// initialise network
		void Init();
		/// try to change your username
		void ChangeUsername(std::string name);
		/// send a username request
		void RequestUsername();
		/// send a login attempt
		void RequestLogin();
		/// send a text message
		void SendTextMessage(string user, string message);
		/// send a file message
		void SendFileMessage(string user, string filename);
		/// handle an incoming message
		void HandleMessage(uint8 type, uint8* data, uint32 size, std::string fromuser);

		/// set new state
		void SetState(NetState newstate);

		/// handle clicks in userlists
		void clickOfflineUser(int i);
		void clickOnlineUser(int i);

		/// find user given an ip
		std::string FindUserByIp(IPaddress ip);

		/// add user to offline list
		void AddOfflineUser(std::string user);

		/// open chat window for a given user
		void OpenChatWindow(std::string username);
};

#endif
